/*
 * Copyright 2010 Christoph Widulle (christoph.widulle@googlemail.com)
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the
 * License. You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS"
 * BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language
 * governing permissions and limitations under the License.
 */



package com.android1.amarena2d.nodes.particle;

import com.android1.amarena2d.annotations.Incomplete;
import com.android1.amarena2d.commons.Tools;
import com.android1.amarena2d.nodes.behavior.LifecyleTick;
import com.android1.amarena2d.nodes.particle.effects.GravityParticleEffect;
import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.math.Vector2;

import static com.android1.amarena2d.commons.Tools.randomMinus1To1;

@Incomplete
public class GravityEmitter extends Emitter<GravityParticle> implements LifecyleTick {

    protected final GravityParticleEffectConfig config;

    public GravityEmitter(GravityParticleEffect effect, int effectLevel, float x, float y) {
        this(effect, effectLevel, x, y, 0, 0);
    }

    public GravityEmitter(GravityParticleEffect effect, int effectLevel, float x, float y, float width, float height) {
        super(effect, effectLevel, x, y, width, height);
        this.config = effect.getEffectConfig();
    }

    private Vector2 tmp = new Vector2();
    private Vector2 radial = new Vector2();
    private Vector2 tangential = new Vector2();


    protected GravityParticle[] createParticles(int count) {

        GravityParticle[] particles = new GravityParticle[count];

        for (int i = 0; i < particles.length; i++) {

            GravityParticle particle = particles[i] = new GravityParticle(i);
            initParticle(particle);

        }
        return particles;
    }

    @Override
    protected void update(GravityParticle p, float d) {

        //todo repair me
        
        // radial acceleration
        radial.set(p.pos.x, p.pos.y).nor();
        tangential.set(radial);
        radial.mul(p.radialAccel);

        // tangential acceleration
        final float newy = tangential.x;
        tangential.x = -tangential.y;
        tangential.y = newy;
        tangential.mul(p.tangentialAccel);

        // (gravity + radial + tangential) * dt
        tmp.set(radial).add(tangential).add(config.gravity).mul(d);

        p.direction.add(tmp);
        tmp.set(p.direction).mul(d);
        p.pos.add(tmp);

        p.color.r += (p.deltaColor.r * d);
        p.color.g += (p.deltaColor.g * d);
        p.color.b += (p.deltaColor.b * d);
        p.color.a += (p.deltaColor.a * d);

        p.color.clamp();

        p.life -= d;

        p.size += Math.max(0, p.deltaSize * d);

        p.rotation += (p.deltaRotation * d);
    }

    @Override
    public GravityParticleEffectConfig getParticleEffectConfig() {
        return config;
    }


    final Vector2 v = new Vector2();
    final Color end = new Color(Color.WHITE);

    protected void initParticle(GravityParticle particle) {

        float a = Tools.degreesToRadians((config.angle + config.angleVar * randomMinus1To1()));
        v.x = (float) Math.cos(a);
        v.y = (float) Math.sin(a);
        
        final float s = config.speed + config.speedVar * randomMinus1To1();
        particle.startDirection.x = v.x * s;
        particle.startDirection.y = v.y * s;

        particle.radialAccel = config.radialAccel + config.radialAccelVar * randomMinus1To1();

        particle.tangentialAccel = config.tangentialAccel + config.tangentialAccelVar * randomMinus1To1();

        particle.timeToLive = this.config.life + this.config.lifeVar * randomMinus1To1();

        particle.color.r = config.startColor.r + config.startColorVar.r * randomMinus1To1();
        particle.color.g = config.startColor.g + config.startColorVar.g * randomMinus1To1();
        particle.color.b = config.startColor.b + config.startColorVar.b * randomMinus1To1();
        particle.color.a = config.startColor.a + config.startColorVar.a * randomMinus1To1();

        particle.startColor.set(particle.color);

        end.r = config.endColor.r + config.endColorVar.r * randomMinus1To1();
        end.g = config.endColor.g + config.endColorVar.g * randomMinus1To1();
        end.b = config.endColor.b + config.endColorVar.b * randomMinus1To1();
        end.a = config.endColor.a + config.endColorVar.a * randomMinus1To1();

        particle.deltaColor.r = (end.r - particle.color.r) / particle.timeToLive;
        particle.deltaColor.g = (end.g - particle.color.g) / particle.timeToLive;
        particle.deltaColor.b = (end.b - particle.color.b) / particle.timeToLive;
        particle.deltaColor.a = (end.a - particle.color.a) / particle.timeToLive;

        particle.startSize = config.startSize + config.startSizeVar * randomMinus1To1();

        if (config.endSize == ParticleEffectConfig.SAME_AS_START)
            particle.deltaSize = 0;
        else {
            final float endS = Math.max(0, config.endSize + config.endSizeVar * randomMinus1To1());
            particle.deltaSize = (endS - particle.startSize) / particle.timeToLive;
        }

        particle.startRotation = config.startSpin + config.startSpinVar * randomMinus1To1();
        final float endA = config.endSpin + config.endSpinVar * randomMinus1To1();
        particle.deltaRotation = (endA - particle.startRotation) / particle.timeToLive;


    }


    @Override
    protected void resetParticle(GravityParticle p) {

        p.pos.x = this.getPosVarX() * randomMinus1To1() + this.position.x;
        p.pos.y = this.getPosVarY() * randomMinus1To1() + this.position.y;
        p.direction.set(p.startDirection);
        p.life = p.timeToLive;
        p.color.set(p.startColor);
        p.size = p.startSize;
        p.rotation = p.startRotation;

    }
}


